package com.workflow.controller;


import com.flowable.FlowProcDefDto;
import com.workflow.service.IFlowDefinitionService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.repository.ModelRepository;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/initFlow")
@Slf4j
public class InitController {


    @Autowired
    private ModelService modelService;



    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private IFlowDefinitionService iFlowDefinitionService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    protected SqlSessionTemplate sqlSessionTemplate;

    @Autowired
    private ModelRepository modelRepository;


    /**
     * 获取定义的模型列表
     * @return ACT_DE_MODEL List集合
     */
    @GetMapping(value = "/getModel")
    public List<Model> getModel(){
        List<Model> business = modelRepository.findByModelType(null, "created_by");
        return business;
    }


    /**
     * 获取部署的流程列表
     * @return ACT_DE_MODEL List集合
     */
    @GetMapping(value = "/getProcdefList")
    public List<FlowProcDefDto> getProcdef(@RequestParam(value = "name",required = false) String name){
        return iFlowDefinitionService.list(name);
    }


    /**
     * 流程部署
     *
     * @param modelId 流程ID，来自 ACT_DE_MODEL
     * @return
     */
    @GetMapping(value = "/deploy/{modelId}")
    public void deploy(@PathVariable(value = "modelId") String modelId) {
        // 根据模型 ID 获取模型
        Model modelData = modelService.getModel(modelId);

        byte[] bytes = modelService.getBpmnXML(modelData);
        if (bytes == null) {
            log.error("模型数据为空，请先设计流程并成功保存，再进行发布");
        }

        BpmnModel model = modelService.getBpmnModel(modelData);
        if (model.getProcesses().size() == 0) {
            log.error("数据模型不符要求，请至少设计一条主线流程");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
        String processName = modelData.getName()+".bpmn20.xml";

        // 部署流程
        repositoryService.createDeployment()
                .name(modelData.getName())
                .addBytes(processName, bpmnBytes)
                .deploy();

        log.info("流程部署成功：" + modelId + " " + new Date());
    }

    /**
     * 启动流程
     *
     * @param deployId 部署的流程Id，来自 ACT_RE_PROCDEF
     * @param userId   用户 Id
     * @param dataKey  标识流程实例的键，可用于稍后通过查询API检索流程实例。
     * @return
     */
    @GetMapping(value = "/start/{deployId}/{userId}/{dataKey}")
    public ProcessInstance start(@PathVariable(value = "deployId") String deployId, @PathVariable(value = "userId") String userId, @PathVariable(value = "dataKey") String dataKey) {
        // 设置发起人
        identityService.setAuthenticatedUserId(userId);
        // 根据流程 ID 启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(deployId, dataKey);
        log.info("流程启动成功：" + deployId + " " + new Date());
        return processInstance;
    }
}
